#ifndef BSNES_H
#define BSNES_H

#include "libsnes.hpp"
#include "pcejin.h"
#include "movie.h"
#include "xstring.h"

extern unsigned int snes_width;
extern unsigned int snes_height;
extern const uint16_t* video_ptr;

#define AUDIO_BUFFER_LENGTH 2048
static int audio_count = 0;
static uint32_t audio_buffer[AUDIO_BUFFER_LENGTH] = { 0 };

static int16_t snes_input_state_handler(bool port, unsigned device, unsigned index, unsigned id)
{
	int i = (port ? 1 : 0) * 4 + index;

//	if (device >= SNES_DEVICE_MOUSE && id <= 1)
//	{
//		return (int16_t)(input_coords[i] >> (id * 16));
//	}
//	else

	return (pcejin.pads[0] & (1 << id)) != 0;
//	{
//		return (input_buttons[i] & (1 << id)) != 0;
//	}
}

static void snes_input_poll_handler()
{
	//what is this supposed to do?
}

static void video_refresh(const uint16_t *data, unsigned width, unsigned height)
{
	video_ptr = data;
	snes_width = width;
	snes_height = height;
}

static void snes_audio_sample_handler(uint16_t left, uint16_t right)
{
	if (audio_count >= AUDIO_BUFFER_LENGTH)
	{
		audio_count = 0;
	}

	audio_buffer[audio_count++] = (right << 16) | left;
}

class Snes {
public:

	char GameName[256];

	bool Load(char* path) {

		FILE* fp;
		u8* buf;

		fp = fopen(path,"rb");

		if(!fp)
			return false;
		fseek(fp,0,SEEK_END);
		int size=ftell(fp);
		fseek(fp,0,SEEK_SET);

		buf = (u8*)malloc(size);
		fread(buf,1,size,fp);

		fclose(fp);

		char drv[256];
		char dir[256];
		char name[256];
		char ext[256];

		splitpath(path,drv,dir,name,ext);
		snprintf(GameName,256,"%s",name);

		snes_init();
		snes_load_cartridge_normal(0,buf,size);

		snes_set_video_refresh(video_refresh);
		snes_set_audio_sample(snes_audio_sample_handler);
		snes_set_input_state(snes_input_state_handler);
		snes_set_input_poll(snes_input_poll_handler);

		return true;
	}

	void Frame() {
		snes_run();
	}

	void Power() {
		snes_power();
	}

	void SaveState(int num) {

		u8* data;

		int size = snes_serialize_size();

		if(!size)
			assert(false);
		//	printf("failure");

		data = (u8*)malloc(size);

		bool result = snes_serialize(data,size);

		if(!result)
			assert(false);
			//printf("failure");

		char filename[256];
		snprintf(filename,255,"%s_%d.bsn",GameName,num);
		FILE* fp = fopen(filename,"wb");
		fwrite(data,size,1,fp);

		fclose(fp);

		SaveStateMovie(filename);
	}

	void LoadState(int num) {

		u8* data;
		int size = snes_serialize_size();
		if(!size) 
			assert(false);
		//	printf("failure");
		data = (u8*)malloc(size);

		char filename[256];
		snprintf(filename,255,"%s_%d.bsn",GameName,num);
		FILE* fp = fopen(filename,"rb");
		fread(data,size,1,fp);
		fclose(fp);

		snes_unserialize(data,size);
		LoadStateMovie(filename);
	}
};

extern Snes snes;
#endif